package com.ht.dsp;

import com.ht.aems.ieeeformat.BranchData;
import com.ht.aems.ieeeformat.BusData;
import com.ht.aems.measure.MeasureInfo;
import com.ht.aems.measure.SystemMeasure;
import com.ht.aems.ntp.CimToIEEE;

import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: Dong Shufeng
 * Date: 12-1-1
 */
public class SeConfReader {
    //standard deviation setting
    //the unit is kV
    public static double sigma_500kv_v = 12;
    public static double sigma_330kv_v = 7.92;
    public static double sigma_220kv_v = 5.28;
    public static double sigma_110kv_v = 2.64;
    public static double sigma_66kv_v = 1.58;
    public static double sigma_other_v = 1;

    //the unit is mw
    public static double sigma_500kv_line_mw = 21.66;
    public static double sigma_330kv_line_mw = 13.72;
    public static double sigma_220kv_line_mw = 6.1;
    public static double sigma_110kv_line_mw = 2.28;
    public static double sigma_66kv_line_mw = 1.394;
    public static double sigma_other_line_mw = 1;

    //the unit is mvar
    public static double sigma_500kv_line_mvar = 32.49;
    public static double sigma_330kv_line_mvar = 20.58;
    public static double sigma_220kv_line_mvar = 9.15;
    public static double sigma_110kv_line_mvar = 3.42;
    public static double sigma_66kv_line_mvar = 2.091;
    public static double sigma_other_line_mvar = 1.5;

    public static double delta_angle = 0.01;
    public static double delta_current = 0.1;
    public static List<String> reversedPoints;

    private CimToIEEE bridge;
    private SystemMeasure systemMeasure;

    private SeConfReader(CimToIEEE bridge, SystemMeasure systemMeasure) {
        this.bridge = bridge;
        this.systemMeasure = systemMeasure;
    }

    static {
        readConf();
    }

    private static void readConf() {
        ResourceBundle rb = ResourceBundle.getBundle("config.seconf");
        sigma_500kv_v = Double.parseDouble(rb.getString("sigma_500kv_v"));
        sigma_330kv_v = Double.parseDouble(rb.getString("sigma_330kv_v"));
        sigma_220kv_v = Double.parseDouble(rb.getString("sigma_220kv_v"));
        sigma_110kv_v = Double.parseDouble(rb.getString("sigma_110kv_v"));
        sigma_66kv_v = Double.parseDouble(rb.getString("sigma_66kv_v"));
        sigma_other_v = Double.parseDouble(rb.getString("sigma_other_v"));

        sigma_500kv_line_mw = Double.parseDouble(rb.getString("sigma_500kv_line_mw"));
        sigma_330kv_line_mw = Double.parseDouble(rb.getString("sigma_330kv_line_mw"));
        sigma_220kv_line_mw = Double.parseDouble(rb.getString("sigma_220kv_line_mw"));
        sigma_110kv_line_mw = Double.parseDouble(rb.getString("sigma_110kv_line_mw"));
        sigma_66kv_line_mw = Double.parseDouble(rb.getString("sigma_66kv_line_mw"));
        sigma_other_line_mw = Double.parseDouble(rb.getString("sigma_other_line_mw"));

        sigma_500kv_line_mvar = Double.parseDouble(rb.getString("sigma_500kv_line_mvar"));
        sigma_330kv_line_mvar = Double.parseDouble(rb.getString("sigma_330kv_line_mvar"));
        sigma_220kv_line_mvar = Double.parseDouble(rb.getString("sigma_220kv_line_mvar"));
        sigma_110kv_line_mvar = Double.parseDouble(rb.getString("sigma_110kv_line_mvar"));
        sigma_66kv_line_mvar = Double.parseDouble(rb.getString("sigma_66kv_line_mvar"));
        sigma_other_line_mvar = Double.parseDouble(rb.getString("sigma_other_line_mvar"));

        int num = Integer.parseInt(rb.getString("reversed_points_num"));
        reversedPoints = new ArrayList<String>(num);
        for (int i = 1; i <= num; i++)
            reversedPoints.add(rb.getString("reversed_point_" + i));
    }

    public static void setReversedPoints(Map<String, Double> analogValues) {
        for (String key : reversedPoints) {
            if (!analogValues.containsKey(key))
                continue;
            analogValues.put(key, -analogValues.get(key));
        }
    }

    public static void setWeiht(CimToIEEE bridge, SystemMeasure systemMeasure) {
        SeConfReader conf = new SeConfReader(bridge, systemMeasure);
        conf.setWeiht();
    }

    private void setWeiht() {
        for (MeasureInfo info : systemMeasure.getBus_v().values()) {
            BusData bus = bridge.getNum2bus().get(Integer.parseInt(info.getPositionId()));
            info.setSigma(getBusVSigma(bus));
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getBus_p().values()) {//todo:is not perfect finished.
            if(info.getGenMVA() > 1e-4)
                info.setSigma(0.02 * info.getGenMVA() / bridge.getIeeeIsland().getTitle().getMvaBase());
            else {
                BusData bus = bridge.getNum2bus().get(Integer.parseInt(info.getPositionId()));
                info.setSigma(getLineMwSigma(bus.getBaseVoltage()));
            }
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getBus_q().values()) { //todo:is not perfect finished.
            if(info.getGenMVA() > 1e-4)
                info.setSigma(0.03 * info.getGenMVA() / bridge.getIeeeIsland().getTitle().getMvaBase());
            else {
                BusData bus = bridge.getNum2bus().get(Integer.parseInt(info.getPositionId()));
                info.setSigma(getLineMvarSigma(bus.getBaseVoltage()));
            }
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getLine_from_p().values()) {
            BranchData b = bridge.getIeeeIsland().getId2branch().get(Integer.parseInt(info.getPositionId()));
            info.setSigma(getLineMwSigma(b));
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getLine_to_p().values()) {
            BranchData b = bridge.getIeeeIsland().getId2branch().get(Integer.parseInt(info.getPositionId()));
            info.setSigma(getLineMwSigma(b));
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getLine_from_q().values()) {
            BranchData b = bridge.getIeeeIsland().getId2branch().get(Integer.parseInt(info.getPositionId()));
            info.setSigma(getLineMvarSigma(b));
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getLine_to_q().values()) {
            BranchData b = bridge.getIeeeIsland().getId2branch().get(Integer.parseInt(info.getPositionId()));
            info.setSigma(getLineMvarSigma(b));
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getBus_a().values()) {
            info.setSigma(delta_angle);
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getLine_from_i_a().values()) {
            info.setSigma(delta_angle);
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getLine_to_i_a().values()) {
            info.setSigma(delta_angle);
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getLine_from_i_amp().values()) {
            info.setSigma(delta_current);
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
        for (MeasureInfo info : systemMeasure.getLine_to_i_amp().values()) {
            info.setSigma(delta_current);
            info.setWeight(1 / info.getSigma() / info.getSigma());
        }
    }
    private double getBusVSigma(BusData bus) {
        double baseV = bus.getBaseVoltage();
        if (baseV > 450 && baseV < 600) {
            return sigma_500kv_v / baseV;
        } else if (baseV > 300 && baseV < 400) {
            return sigma_330kv_v / baseV;
        } else if (baseV > 200 && baseV < 300) {
            return sigma_220kv_v / baseV;
        } else if (baseV > 100 && baseV < 150) {
            return sigma_110kv_v / baseV;
        } else if (baseV > 60 && baseV < 100) {
            return sigma_66kv_v / baseV;
        } else
            return sigma_other_v / baseV;
    }

    private double getLineMwSigma(BranchData b) {
        double baseV = Math.max(bridge.getNum2bus().get(b.getTapBusNumber()).getBaseVoltage(),
                bridge.getNum2bus().get(b.getZBusNumber()).getBaseVoltage());
        return  getLineMwSigma(baseV);
    }

    private double getLineMwSigma(double baseV) {
        double mvaBase = bridge.getIeeeIsland().getTitle().getMvaBase();
        if (baseV > 450 && baseV < 600) {
            return sigma_500kv_line_mw / mvaBase;
        } else if (baseV > 300 && baseV < 400) {
            return sigma_330kv_line_mw / mvaBase;
        } else if (baseV > 200 && baseV < 300) {
            return sigma_220kv_line_mw / mvaBase;
        } else if (baseV > 100 && baseV < 150) {
            return sigma_110kv_line_mw / mvaBase;
        } else if (baseV > 60 && baseV < 100) {
            return sigma_66kv_line_mw / mvaBase;
        } else
            return sigma_other_line_mw / mvaBase;
    }

    private double getLineMvarSigma(BranchData b) {
        double baseV = Math.max(bridge.getNum2bus().get(b.getTapBusNumber()).getBaseVoltage(),
                bridge.getNum2bus().get(b.getZBusNumber()).getBaseVoltage());
        return  getLineMvarSigma(baseV);
    }

    private double getLineMvarSigma(double baseV) {
        double mvaBase = bridge.getIeeeIsland().getTitle().getMvaBase();
        if (baseV > 450 && baseV < 600) {
            return sigma_500kv_line_mvar / mvaBase;
        } else if (baseV > 300 && baseV < 400) {
            return sigma_330kv_line_mvar / mvaBase;
        } else if (baseV > 200 && baseV < 300) {
            return sigma_220kv_line_mvar / mvaBase;
        } else if (baseV > 100 && baseV < 150) {
            return sigma_110kv_line_mvar / mvaBase;
        } else if (baseV > 60 && baseV < 100) {
            return sigma_66kv_line_mvar / mvaBase;
        } else
            return sigma_other_line_mvar / mvaBase;
    }
}
